package com.todod.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.todod.entity.Basefile;
import com.todod.exception.UploadFileException;
import com.todod.model.BaseFile;

@Component
public class FileUtil {

	private static String visi;

	private static String uploadPath; // 文件路径

	private static String showPath; // 映射路径

//	private static Map<String, BaseFile> basefileMap = new HashMap<String, BaseFile>();
	private static ConcurrentHashMap<String, BaseFile> basefileMap = new ConcurrentHashMap<String, BaseFile>();

	@Value("${file.visit}")
	public void setVisi(String visi) {
		FileUtil.visi = visi;
	}

	@Value("${file.upload.path}")
	public void setUploadPath(String path) {
		FileUtil.uploadPath = path;
	}

	@Value("${file.upload.mapping}")
	public void setShowPath(String mapping) {
		FileUtil.showPath = mapping;
	}

	public static String getVisi() {
		return visi;
	}

	public static String getUploadPath() {
		return uploadPath;
	}

	public static String getShowPath() {
		return showPath;
	}

	public static Map<String, BaseFile> getBasefileMap() {
		return basefileMap;
	}

	/**
	 * w文件上传方法 文件保存在basefileMap中
	 * 
	 * @param _userId id
	 * @param request request
	 * @param ant     uploadname
	 * @author hyw
	 */

	public static void upload(Long _userId, HttpServletRequest request, String ant, String filetype, String fileCo) {
		try {
			String newDate = TododDate.getInstance().getSimpledate();

			MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
			MultipartFile uploadFile = req.getFile(ant);

			// 上传路径
			String root = uploadPath;

			String abstractPath = root + "upload" + File.separator + newDate;

			String rPath = showPath + "upload" + "/" + newDate;

			File dir = new File(abstractPath);
			if (!dir.exists()) {
				dir.mkdirs();
			}

			String originalName = uploadFile.getOriginalFilename();
			String suffix = StringUtils.substringAfterLast(originalName, ".");

			String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + suffix;
			// 保存数据
			FileCopyUtils.copy(uploadFile.getInputStream(),
					new FileOutputStream(abstractPath + File.separator + fileName));

			String relativePath = rPath + "/" + fileName;
			// 封装数据
			/*
			 * fengzhuang(_userId, originalName, fileName, suffix, uploadFile.getSize(),
			 * abstractPath + File.separator + fileName, relativePath);
			 */

			BaseFile kxFile = new BaseFile();
			kxFile.setId(SnowflakeIdGenerator.getId());

			kxFile.setOriginalName(originalName);
			kxFile.setFileSize(uploadFile.getSize());
			kxFile.setFileName(fileName);
			kxFile.setFileType(suffix);
			kxFile.setSuffix(suffix);
			kxFile.setAbstractPath(abstractPath + File.separator + fileName);
			kxFile.setRelativePath(relativePath);

			if (basefileMap.size() > 0) {
				kxFile.setSortNum(basefileMap.size() + 1);
			} else {
				kxFile.setSortNum(1);
			}

			kxFile.setCreateuserId(_userId);
			kxFile.setCreatetimeTi(LocalDateTime.now());
			basefileMap.put(originalName, kxFile);

		} catch (Exception e) {

			throw new UploadFileException("上传文件失败");
		}

	}

	/**
	 * 
	 * @param t 目标file对象 目标属性名要和Basefile 属性名一致
	 * @return
	 * @throws Exception
	 */
	public static <T> Map<String, T> transfor(Class<T> t) throws Exception {
		if (basefileMap.isEmpty()) {
			throw new RuntimeException();
		}
		Map<String, T> targetMap = new HashMap<String, T>();
		for (String key : basefileMap.keySet()) {
			T newInstance = t.newInstance();
			BeanUtils.copyProperties(newInstance, basefileMap.get(key));
			targetMap.put(key, newInstance);
		}

		return targetMap;

	}

	/**
	 * w 文件上传返回目标 file basefilemap 不保存数据 需要设定filesortNum
	 * 
	 * @param _userId
	 * @param request
	 * @param ant
	 * @param t
	 * @return
	 */

	public static <T> T upload(Long _userId, HttpServletRequest request, String ant, Class<T> t) {
		try {
			String newDate = TododDate.getInstance().getSimpledate();

			MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
			MultipartFile uploadFile = req.getFile(ant);

			// 上传路径
			String root = uploadPath;

			String abstractPath = root + "upload" + File.separator + newDate;

			String rPath = showPath + "upload" + "/" + newDate;

			File dir = new File(abstractPath);
			if (!dir.exists()) {
				dir.mkdirs();
			}

			String originalName = uploadFile.getOriginalFilename();
			String suffix = StringUtils.substringAfterLast(originalName, ".");

			String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + suffix;
			// 保存数据
			FileCopyUtils.copy(uploadFile.getInputStream(),
					new FileOutputStream(abstractPath + File.separator + fileName));

			String relativePath = rPath + "/" + fileName;
			// 封装数据
			/*
			 * fengzhuang(_userId, originalName, fileName, suffix, uploadFile.getSize(),
			 * abstractPath + File.separator + fileName, relativePath);
			 */

			Basefile basefile = new Basefile();
			basefile.setId(SnowflakeIdGenerator.getId());

			basefile.setOriginalName(originalName);
			basefile.setFileSize(uploadFile.getSize());
			basefile.setFileName(fileName);
			basefile.setFileType(suffix);
			basefile.setSuffix(suffix);
			basefile.setAbstractPath(abstractPath);
			basefile.setRelativePath(relativePath);
			basefile.setLinkName(suffix);

//			  if (basefileMap.size()>0) { basefile.setSortNum(basefileMap.size()+1); }else {
//				  basefile.setSortNum(1); }

			basefile.setCreateUserId(_userId);
			basefile.setCreateTime(LocalDateTime.now());
//			basefileMap.put(originalName, basefile); 
			T newInstance = t.newInstance();
			BeanUtils.copyProperties(newInstance, basefile);
			return newInstance;
		} catch (Exception e) {

			throw new UploadFileException("上传文件失败");
		}

	}

	/**
	 * x 文件下载
	 * 
	 * @param request
	 * @param response
	 * @param path
	 * @param fileName
	 * @throws Exception
	 */
	public static void download(HttpServletRequest request, HttpServletResponse response, String path, String fileName)
			throws Exception {
		File file = new File(path);
		if (file.isFile()) {
			// 设置页面不缓存,清空buffer
			response.reset();
			response.setCharacterEncoding("UTF-8");// 字符编码
			// response.setContentType("application/octet-stream");
			response.setContentType("multipart/form-data");// 二进制传输数据
//			response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
			response.addHeader("Access-Control-Allow-Origin", "*");
			response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
			// 设置信息给客户端不解析
			// String type = new MimetypesFileTypeMap().getContentType(fileName);
			String type = Files.probeContentType(Paths.get(path));
//			// 设置contenttype，即告诉客户端所发送的数据属于什么类型
			response.setHeader("Content-type", type);
			FileInputStream input = new FileInputStream(file);
			ServletOutputStream out = response.getOutputStream();
			byte[] buff = new byte[1024];
			int index = 0;
			while ((index = input.read(buff)) != -1) {
				out.write(buff, 0, index);
				out.flush();
			}
			out.close();
			input.close();
		}
	}

	/**
	 * basemap清除list包含的key-value 和文件
	 * 
	 * @param list
	 */
	public static void deletefile(List<String> list) {
		for (String key : list) {
			File file = new File(basefileMap.get(key).getAbstractPath());
			if (file.isFile()) {
				file.delete();
			}
			basefileMap.remove(key);
		}
	}

	/**
	 * basemap清除list包含的key-value
	 * 
	 * @param list
	 */
	public static void updateMap(List<String> list) {
		for (String key : list) {
			basefileMap.remove(key);
		}
	}

	/**
	 * s根据id删除上传未保存的文件
	 * 
	 * @param id
	 */
	public static void deletebyCondition(Long id) {
		ArrayList<String> arrayList = new ArrayList<>();
		for (String key : basefileMap.keySet()) {
			BaseFile basefile = basefileMap.get(key);
			if (String.valueOf(id).equals(String.valueOf(basefile.getCreateuserId()))) {
				arrayList.add(key);
			}
		}
		deletefile(arrayList);
		arrayList.clear();

	}

	/**
	 * s根据id 和name 删除 单个文件
	 * 
	 * @param id
	 * @param name
	 */
	public static void deletebyCondition(Long id, String name) {
		ArrayList<String> arrayList = new ArrayList<>();
		for (String key : basefileMap.keySet()) {
			BaseFile basefile = basefileMap.get(key);
			if (String.valueOf(id).equals(String.valueOf(basefile.getCreateuserId())) && name.equals(key)) {
				arrayList.add(key);
			}
		}

		deletefile(arrayList);
		arrayList.clear();

	}

	/**
	 * basemap清除Set包含的key-value 和文件
	 *
	 * @param list
	 */
	public static void deletefile(Set<String> list) {
		if (!basefileMap.isEmpty() && list.size() > 0) {
			for (String key : list) {
				File file = new File(basefileMap.get(key).getAbstractPath());
				if (file.isFile()) {
					file.delete();
				}
				basefileMap.remove(key);
			}
		}

	}

	/**
	 * basemap清除Set包含的key-value
	 *
	 * @param list
	 */
	public static void updateMap(Set<String> list) {
		if (!basefileMap.isEmpty() && list.size() > 0) {
			for (String key : list) {
				basefileMap.remove(key);
			}

		}

	}

}
